<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Promise</title>
</head>
<body>
    <div>Writing Promise</div>



    <script>
        const PENDING = 'pending'
        const RESOLVED = 'resolved'
        const REJECTED = 'rejected'

        function MyPromise(fn) {
            const that = this
            that.state = PENDING
            that.value = null
            that.resolvedCallbacks = []
            that.rejectedCallbacks = []

            function resolve(value) {
                if (that.state === PENDING) {
                    that.state = RESOLVED
                    that.value = value
                    that.rejectedCallbacks.map(cb => cb(that.value))
                }
            }

            function reject(value) {
                if (that.state === PENDING) {
                    that.state = REJECTED
                    that.value = value
                    that.rejectedCallbacks.map(cb => cb(that.value))
                }
            }

            try {
                fn(resolve, reject)
            } catch (e) {
                reject(e)
            }

        }

        MyPromise.prototype.then = function(onFulfilled, onRejected) {
            const that = this
            onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v
            onRejected = typeof onRejected === 'function'
                ? onRejected
                : r => {
                    throw r
                }

                if (that.state === PENDING) {
                    that.resolvedCallbacks.push(onFulfilled)
                    that.rejectedCallbacks.push(onRejected)
                }

                if (that.state === RESOLVED) {
                    onFulfilled(that.value)
                }

                if (that.state === REJECTED) {
                    onRejected(that.value)
                }
        }


    </script>
</body>
</html>